package com.xiaoma.drools;

import android.content.Context;
import android.os.AsyncTask;
import android.util.Log;

import com.xiaoma.bean.Message;
import com.xiaoma.bean.VDatas;
import com.xiaoma.vpa.MainActivity;

import org.drools.core.impl.InternalKnowledgeBase;
import org.drools.core.impl.KnowledgeBaseFactory;
import org.kie.api.KieBase;
import org.kie.api.io.ResourceType;
import org.kie.api.runtime.Channel;
import org.kie.api.runtime.KieSession;
import org.kie.api.runtime.StatelessKieSession;
import org.kie.api.runtime.rule.FactHandle;
import org.kie.internal.builder.KnowledgeBuilder;
import org.kie.internal.builder.KnowledgeBuilderFactory;
import org.kie.internal.command.CommandFactory;
import org.kie.internal.io.ResourceFactory;
import org.mvel2.util.Make;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import static com.xiaoma.bean.VDatas.DRIVER_SLEEPY;

/**
 * @Class: 规则drl文件测试
 * @Description:
 * @author: qiurudong
 * @Date: 2020/12/30 0030
 */
public class DroolsStateSession {
    private final String TAG = DroolsStateSession.class.getName();
    private Context context;
    private Map<String, KnowledgeBuilder> knowledgeBuilderMap = new ConcurrentHashMap<>();
    private InternalKnowledgeBase kBase = null;

    public DroolsStateSession(Context context) {
        this.context = context.getApplicationContext();
    }

    public void stateFulSession() {
        try {
            initDrl("vpa_engine_rule.drl");
            KieSession kieSession = kBase.newKieSession();
            kieSession.registerChannel("log", new Channel() {
                @Override
                public void send(Object object) {
                    Log.d(TAG, object.toString());
                }
            });
            VDatas vDatas = createData(110, DRIVER_SLEEPY);
            FactHandle handle = kieSession.insert(vDatas);
            int count = kieSession.fireAllRules();
            Log.d(TAG, String.format("有状态匹配 第一次， 匹配成功数量%d, Scene %s, Speed %d", count, vDatas.getScene(), vDatas.getSpeed()));

            vDatas.setSpeed(50);
            kieSession.update(handle, vDatas);
            count = kieSession.fireAllRules();
            Log.d(TAG, String.format("有状态匹配 第二次， 匹配成功数量%d, Scene %s, Speed %d", count, vDatas.getScene(), vDatas.getSpeed()));

            kieSession.dispose();
        } catch (Exception e) {
            Log.e(TAG, "Drools exception", e);
        }
    }

    public void stateLessSession() {
        try {
            initDrl("vpa_engine_rule.drl");
            StatelessKieSession kieSession = kBase.newStatelessKieSession();
            kieSession.registerChannel("log", new Channel() {
                @Override
                public void send(Object object) {
                    Log.d(TAG, object.toString());
                }
            });
            VDatas vDatas = createData(110, DRIVER_SLEEPY);
            List list = new ArrayList();
            list.add(CommandFactory.newInsert(vDatas));
            kieSession.execute(CommandFactory.newBatchExecution(list));
            Log.d(TAG, String.format("无状态匹配 execute command测试 Scene %s, Speed %d", vDatas.getScene(), vDatas.getSpeed()));

            VDatas vDatas2 = createData(50, DRIVER_SLEEPY);
            kieSession.execute(vDatas2);
            Log.d(TAG, String.format("无状态匹配 execute object测试 Scene %s, Speed %d", vDatas2.getScene(), vDatas2.getSpeed()));
        } catch (Exception e) {
            Log.e(TAG, "Drools exception", e);
        }
    }

    public void multiDrl() {
        try {
            initDrl("vpa_engine_rule.drl");
            initDrl("HelloWorld.drl");
            KieSession kieSession = kBase.newKieSession();
            kieSession.registerChannel("log", new Channel() {
                @Override
                public void send(Object object) {
                    Log.d(TAG, "channel log " + object.toString());
                }
            });
            VDatas vDatas = createData(110, DRIVER_SLEEPY);
            Message message = createMessage("小马立行", 0);
            kieSession.insert(vDatas);
            kieSession.insert(message);
            int count = kieSession.fireAllRules();
            Log.d(TAG, String.format("多drl匹配 匹配成功数量%d, Scene %s, Speed %d, message %s, status %d",
                    count, vDatas.getScene(), vDatas.getSpeed(), message.getMessage(), message.getStatus()));
            kieSession.dispose();
        } catch (Exception e) {
            Log.e(TAG, "Drools exception", e);
        }
    }


    private void initDrl(String drlFileName) {
        if (knowledgeBuilderMap.get(drlFileName) != null) return;
        try {
            KnowledgeBuilder kb = KnowledgeBuilderFactory.newKnowledgeBuilder();
            String drl = getTxtFromAssets(context, drlFileName);
            kb.add(ResourceFactory.newByteArrayResource(drl.getBytes("utf-8")), ResourceType.DRL);
            if (kb.hasErrors()) {
                String errorMessage = kb.getErrors().toString();
                Log.e(TAG, "规则语法异常---\n" + errorMessage);
                return;
            }
            knowledgeBuilderMap.put(drlFileName, kb);
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
            return;
        }
        if (kBase == null) {
            kBase = KnowledgeBaseFactory.newKnowledgeBase();
        }
        kBase.addPackages(knowledgeBuilderMap.get(drlFileName).getKnowledgePackages());
    }

    private VDatas createData(int speed, int driverAction) {
        VDatas vDatas = new VDatas();
        vDatas.setSpeed(speed);
        vDatas.setDriverAction(driverAction);
        return vDatas;
    }

    private Message createMessage(String messageStr, int status) {
        Message message = new Message();
        message.setMessage(messageStr);
        message.setStatus(status);
        return message;
    }

    private String getTxtFromAssets(Context context, String fileName) {
        String result = "";
        try {
            InputStream is = context.getAssets().open(fileName);
            int lenght = is.available();
            byte[] buffer = new byte[lenght];
            is.read(buffer);
            result = new String(buffer, "utf8");
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }

    public void helloPublicFunction(){
        Log.d(DroolsStateSession.class.getName(), "Hello Public Function");
    }

    public static void helloStaticFunction(){
        Log.d(DroolsStateSession.class.getName(), "Hello Static Function");
    }

}
